package org.gvp.generator.core.writer.impl;

import org.gvp.generator.constant.ImportConstant;
import org.gvp.generator.core.writer.AbstractFileWriter;
import org.gvp.generator.props.CreateProps;
import org.gvp.generator.props.ProjectProps;
import org.gvp.generator.table.TableInfo;

import java.nio.file.Path;
import java.nio.file.Paths;

/**
 * 数据层代码生成类
 */
public class ControllerFileWriter extends AbstractFileWriter {
    @Override
    public void execute(TableInfo tableInfo, ProjectProps project) {
        String upName = tableInfo.getUpperName();
        String lowName = tableInfo.getLowerName();
        String prefix = project.getRequestMappingPrefix() == null ? "" : project.getRequestMappingPrefix() + "/" ;
        String classDefine = """
                @RestController
                @RequestMapping("/%s%s")
                @RequiredArgsConstructor
                public class %sController implements BaseController<%s> {
                    private final %sService %sService;
                """.formatted(prefix,tableInfo.getTableName().replaceAll("_","-"),upName,upName,upName,lowName);

        channel.writeNewline(project.getBasePackageImport() + project.getControllerPackage() + ";");
        channel.writeEmptyLine();
        channel.writeNewline(ImportConstant.LOMBOK_REQ_CONS);
        channel.writeNewline(ImportConstant.SPRING_REST_CONTROLLER);
        channel.writeNewline(ImportConstant.SPRING_REST_MAPPING_ALL);
        channel.writeEmptyLine();
        channel.writeNewline(ImportConstant.COMMON_CONTROLLER_IMPORT);
        channel.writeNewline(ImportConstant.COMMON_OPERATION_ANNOTATION_IMPORT);
        channel.writeNewline(ImportConstant.COMMON_PAGE);
        channel.writeNewline(ImportConstant.COMMON_RESULT);
        channel.writeNewline(project.getBaseImport() + project.getServicePackage() + "." + upName + "Service;");
        channel.writeNewline(project.getEntityImport());
        channel.writeNewline(ImportConstant.LIST);
        channel.writeEmptyLine();
        channel.writeNewline(classDefine);
        writeMethod(upName,lowName,tableInfo.getRemark());
        channel.writeNewline("}");
    }


    public void writeMethod(String upName,String lowName,String remark){
        String add = """
                    @PutMapping
                    @Operation(value = "添加%s数据",param = "%s实体类对象")
                    @Override
                    public Result<Integer> add(@RequestBody %s pojo) {
                        return Result.ok(this.%sService.save(pojo));
                    }
                """.formatted(remark,remark,upName,lowName);
        String addAndReturn = """
                    @PutMapping("/return")
                    @Operation(value = "添加%s数据,并反回新数据",param = "%s实体类对象")
                    @Override
                    public Result<%s> addAndReturn(@RequestBody %s pojo) {
                        return Result.ok(this.%sService.saveAndReturn(pojo));
                    }
                """.formatted(remark,remark,upName,upName,lowName);
        String deleteById = """
                    @DeleteMapping("/{id:\\\\d+}")
                    @Operation(value = "删除%s数据", param = "id: %s数据编号")
                    @Override
                    public Result<Integer> deleteById(@PathVariable Integer id) {
                        return Result.ok(this.%sService.removeById(id));
                    }
                """.formatted(remark,remark,lowName);
        String update = """
                    @PostMapping
                    @Operation(value = "使用编号更新%s数据", param = "pojo: %s数据,数据编号(ID)必须存在")
                    @Override
                    public Result<Integer> update(@RequestBody %s pojo) {
                        return Result.ok(this.%sService.edit(pojo));
                    }
                """.formatted(remark,remark,upName,lowName);
        String updateAndReturn = """
                    @PostMapping("/return")
                    @Operation(value = "使用编号更新%s数据,更新之后反回新的数据", param = "pojo: %s数据,数据编号(ID)必须存在")
                    @Override
                    public Result<%s> updateAndReturn(@RequestBody %s pojo) {
                        return Result.ok(this.%sService.editAndReturn(pojo));
                    }
                """.formatted(remark,remark,upName,upName,lowName);
        String queryById = """
                    @GetMapping("/{id:\\\\d+}")
                    @Operation(value = "根据ID查找%s数据", param = "id: %s数据ID")
                    @Override
                    public Result<%s> queryById(@PathVariable Integer id) {
                        return Result.ok(this.%sService.findById(id));
                    }
                """.formatted(remark,remark,upName,lowName);
        String queryList = """
                    @GetMapping("/list")
                    @Operation("获取%s数据列表")
                    @Override
                    public Result<List<%s>> queryList() {
                        return Result.ok(this.%sService.findList());
                    }
                """.formatted(remark,upName,lowName);
        String queryLimit = """
                    @GetMapping("/limit/{start:\\\\d+}/{end:\\\\d+}")
                    @Operation(value = "查找指定区间的%s数据列表",param = "start: 起始位置, end: 结束位置")
                    @Override
                    public Result<List<%s>> queryLimit(@PathVariable int start,@PathVariable int end) {
                        return Result.ok(%sService.findLimit(start, end));
                    }
                """.formatted(remark,upName,lowName);
        String queryCount = """
                    @GetMapping("/count")
                    @Operation("查找%s全部数据列表")
                    @Override
                    public Result<Long> queryCount() {
                        return Result.ok(this.%sService.findCount());
                    }
                """.formatted(remark,lowName);
        String queryPage = """
                    @GetMapping("/page/{page:\\\\d+}/{size:\\\\d+}")
                    @Operation(value = "分页查找%s数据", param = "currentPage: 当前页, pageSize: 页大小")
                    @Override
                    public Result<Page<%s>> queryPage(@PathVariable int page,@PathVariable int size) {
                        return Result.ok(this.%sService.findPage(page, size));
                    }
                """.formatted(remark,upName,lowName);
        channel.writeNewline(add);
        channel.writeNewline(addAndReturn);
        channel.writeNewline(deleteById);
        channel.writeNewline(update);
        channel.writeNewline(updateAndReturn);
        channel.writeNewline(queryById);
        channel.writeNewline(queryList);
        channel.writeNewline(queryLimit);
        channel.writeNewline(queryCount);
        channel.writeNewline(queryPage);
    }

    @Override
    public boolean isWriterFile(CreateProps create) {
        return create.isCreateController();
    }

    @Override
    public Path getFilePath(String basePath, ProjectProps project, String fileName) {
        return Paths.get(basePath, project.getControllerPackage(),fileName + "Controller.java");
    }
}
